package dao

import (
	"context"
	"github.com/qiniu/qmgo"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"monoblog/config"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"strings"
	"sync"
	"time"
)

var (
	accessLogRepo *AccessLogRepository // 单例实例存储变量
	once9         sync.Once            // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewAccessLogRepository() *AccessLogRepository {
	once9.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		accessLogRepo = &AccessLogRepository{
			collection: config.GetDataBase().Collection(model.AccessLogCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return accessLogRepo // 返回唯一实例
}

type AccessLogRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

func (impl *AccessLogRepository) Save(accessLog *model.AccessLog) error {
	if accessLog.CreateTime.IsZero() {
		accessLog.CreateTime = time.Now()
	}
	//保存db
	r, err := impl.collection.InsertOne(impl.ctx, accessLog)
	if oid, ok := r.InsertedID.(primitive.ObjectID); ok {
		accessLog.ID = oid.Hex()
	}
	return err
}

func (impl *AccessLogRepository) FindList(query dto.AccessLogQuery) ([]*model.AccessLog, int, error) {
	var list = make([]*model.AccessLog, 0)

	filter := bson.M{} // 构建查询条件：空条件

	if query.ClientIp != "" {
		filter["clientIp"] = query.ClientIp
	}

	if query.Aid != "" {
		filter["aid"] = query.Aid
	}

	query.Uri = strings.TrimSpace(query.Uri)
	if query.Uri != "" {
		filter["path"] = bson.M{"$regex": query.Uri}
	}

	//条件：创建时间范围 - 开始时间&&结束时间
	if query.StartTime != "" && query.EndTime != "" {
		startTime, err := time.ParseInLocation("2006-01-02T15:04:05", query.StartTime, time.Local)
		endTime, err := time.ParseInLocation("2006-01-02T15:04:05", query.EndTime, time.Local)
		if err == nil {
			filter["createTime"] = bson.M{"$gte": startTime}
			filter["createTime"] = bson.M{"$lte": endTime}
		}
	}

	var total int
	if !query.IsZero() {
		//查询条数
		n, _ := impl.collection.Find(impl.ctx, filter).Count()
		total = int(n)
	}

	//分页查询
	err := impl.collection.Find(impl.ctx, filter).
		Sort(query.SortField()). //排序字段
		Skip(int64(query.Offset())).Limit(int64(query.Limit())).
		All(&list)
	return list, total, err
}
